#include "symbole.h"

/*Constructeur d'un symbôle*/
struct symbole* constrSymbole(char Nom[512], int typeI, int typeL, char Valeur[512], int Emplacement, int Deplacement, char NomEmplacement[128], int nParam, int passage)
{
	struct symbole *nouveau=malloc(sizeof(struct symbole));
	
	strcpy(nouveau->nom, Nom);
	strcpy(nouveau->nomEmplacement, NomEmplacement);

	int isVar=1;
	switch(typeI)
	{
		case var_entier:
			strcpy(nouveau->valeur, "0");
			break;

		case var_reel:
			strcpy(nouveau->valeur, "0.0");
			break;

		case var_char:
			strcpy(nouveau->valeur, "x");
			break;

		case var_string:
			strcpy(nouveau->valeur, "Aucune");
			break;

		case var_byte:
			strcpy(nouveau->valeur, "0");
			break;

		case var_boolean:
			strcpy(nouveau->valeur, "false");
			break;
		
		default:
			isVar=0;
			break;
	}

	if(isVar==0)
		strcpy(nouveau->valeur, Valeur);

	nouveau->typeIdentificateur=typeI;
	nouveau->typeLiteral=typeL;
	nouveau->emplacement=Emplacement;
	nouveau->deplacement=Deplacement;
	nouveau->nParam=nParam;
	nouveau->passage=passage;
	nouveau->ptrPile=-1;

	nouveau->suivant=NULL;
	nouveau->precedent=NULL;
	nouveau->dimension=dimension(typeI);

	return nouveau;
}

struct symbole* constrSimpleSymbole(char Nom[512], char Valeur[512], int Emplacement,  char NomEmplacement[128], int nParam, int passage)
{
	struct symbole *nouveau=malloc(sizeof(struct symbole));
	
	strcpy(nouveau->nom, Nom); 
	strcpy(nouveau->valeur, Valeur); 
	strcpy(nouveau->nomEmplacement, NomEmplacement);
	nouveau->suivant=NULL; 
	nouveau->precedent=NULL; 
	nouveau->dimension=-1; 
	nouveau->emplacement=Emplacement; 
	nouveau->nParam=nParam;
	nouveau->passage=passage;
	nouveau->ptrPile=-1;

	return nouveau;
}

/*Constructeur d'une liste*/
struct liste* constrListe()
{
	struct liste *nouveau=malloc(sizeof(struct liste));

	nouveau->nbElem=0;
	nouveau->tete=NULL;
	nouveau->queue=NULL;

	return nouveau;
}

/*
*	Ajouter un symbôle à la liste à la queue
*	Retourne -1 si erreur
*/
int ajouterSymbole(struct liste* lst,  char nom[512], int typeI, int typeL, char valeur[512], int emplacement, int deplacement, char NomEmplacement[128], int nParam, int passage)
{
	struct symbole *nouveau=constrSymbole(nom, typeI, typeL, valeur, emplacement, deplacement, NomEmplacement, nParam, passage);
	
	if(lst->nbElem==0)
	{
		lst->tete=lst->queue=nouveau;
		lst->nbElem++;
	}
	else
	{
		lst->queue->suivant=nouveau;
		nouveau->precedent=lst->queue;
		lst->queue=nouveau;	
		lst->nbElem++;
	}
	
	return 0;
}

int ajouterSimpleSymbole(struct liste *lst, char nom[512], char valeur[512], int emplacement, char NomEmplacement[128], int nParam, int passage)
{
	struct symbole *nouveau=constrSimpleSymbole(nom, valeur, emplacement, NomEmplacement, nParam, passage);

	if(lst==NULL) return -1;

	if(lst->nbElem==0)
	{
		lst->tete=lst->queue=nouveau; 
		lst->nbElem++;
	}
	else
	{
		lst->queue->suivant=nouveau;
		nouveau->precedent=lst->queue;
		lst->queue=nouveau;	
		lst->nbElem++;
	}

	return 0;
}
struct liste * ajouterListeSymbole(struct liste *src, struct liste *dest)
{
	if(src==NULL || dest==NULL) return NULL;

	struct symbole *tmp=src->tete;
	struct liste *erreur=constrListe();
	struct symbole *trouve;
	int i=0;

	if(dest->nbElem>0)
	{
		while(tmp!=NULL)
		{
			if(strcmp(tmp->nomEmplacement, dest->tete->nomEmplacement)==0) i++;
			else tmp->deplacement=-1;
		
			tmp=tmp->suivant;
		}
	}

	tmp=dest->tete;
	while(tmp!=NULL)
	{
		trouve=chercherUnSymbole(src, tmp->nom, -1, tmp->nomEmplacement);
		
		if(trouve!=NULL)
		{
			ajouterSimpleSymbole(erreur, trouve->nom, trouve->valeur, trouve->emplacement, trouve->nomEmplacement, trouve->nParam, trouve->passage);
		}
		else ajouterSymbole(src,  tmp->nom, tmp->typeIdentificateur, tmp->typeLiteral, tmp->valeur, tmp->emplacement, i, tmp->nomEmplacement, tmp->nParam, tmp->passage);

		i++;
		tmp=tmp->suivant;
	}

	if(erreur->nbElem>0) return erreur;
	else return NULL;
}

/*
*	Supprime un élément de la liste
*	Retourne NULL si erreur sinon retourne le symbole
*/
struct symbole* enleverSymbole(struct liste* lst, char Nom[512],  char NomEmplacement[128])
{
	struct symbole *courant;

	if(lst!=NULL && lst->nbElem>0)
	{
		courant=lst->tete;

		while(courant!=NULL)
		{
			if(strcmp(courant->nom, Nom)==0 && strcmp(courant->nomEmplacement, NomEmplacement)==0)
			{
				if(courant==lst->queue)
				{
					lst->queue=courant->precedent;
					courant->precedent->suivant=NULL;
					lst->nbElem--;
					return courant;
				}
				else if(courant==lst->tete)
				{
					lst->tete=lst->tete->suivant;
					lst->tete->precedent=NULL;
					lst->nbElem--;
					return courant;
				}
				else
				{
					courant->precedent->suivant=courant->suivant;
					courant->suivant->precedent=courant->precedent;
					lst->nbElem--;
					return courant;
				}
			}

			courant=courant->suivant;
		}
	}
	else return NULL;
}

/*
* Recherche un symbôle dans la table des symbôles
* Retourne le symbôle ou NULL si erreur
*/
struct liste* chercherSymbole(struct liste* lst, char Nom[512])
{
	if(lst==NULL || lst->nbElem==0) return NULL;
	
	struct symbole *courant=lst->tete;
	struct liste *res=constrListe();

	while(courant!=NULL)
	{
		if(strcmp(courant->nom, Nom)==0) ajouterSymbole(res, courant->nom, courant->typeIdentificateur, courant->typeLiteral, courant->valeur, courant->emplacement, courant->deplacement, courant->nomEmplacement, courant->nParam, courant->passage);
		courant=courant->suivant;
	}

	return res;
}

/*Renvoi 0 si le symbole n'a pas été trouvé, 1 sinon*/
struct symbole* chercherUnSymbole(struct liste* lst, char Nom[512], int emplacement,  char NomEmplacement[128])
{
	if(lst==NULL || lst->nbElem==0) return 0;
	
	struct symbole *courant=lst->tete;
	struct symbole *ret=NULL;

	if(emplacement!=-1) // On prend en compte son emplacement
	{
		while(courant!=NULL)
		{
			if(strcmp(courant->nom, Nom)==0 && courant->emplacement==emplacement && strcmp(courant->nomEmplacement, NomEmplacement)==0)
				return courant;
		
			courant=courant->suivant;
		}
	}
	else // On prend en compte uniquement son nom et sa localisation
	{
		while(courant!=NULL)
		{
			if(strcmp(courant->nom, Nom)==0 && strcmp(courant->nomEmplacement, NomEmplacement)==0)
				return courant;
			courant=courant->suivant;
		}
	}

	return ret;
}

struct symbole* chercherUnSymbole2(struct liste* lst, int deplacement)
{
	if(lst==NULL || lst->nbElem==0) return 0;
	
	struct symbole *courant=lst->tete;
	struct symbole *ret=NULL;


	while(courant!=NULL)
	{
		if(deplacement==courant->deplacement)
			return courant;

		courant=courant->suivant;
	}

	return NULL;
}

/*Affichage*/
void affichage(struct liste *lst)
{
	printf("\nInformation sur la table des symboles:\nTaille=%d\n\n", lst->nbElem);

	if(lst!=NULL && lst->nbElem>0)
	{
		struct symbole *courant=lst->tete;
	
		while(courant!=NULL)
		{
			printf("Nom=%s; TypeId=%d; TypeVal=%d; Valeur=%s; Dimension=%d; Emplacement=%d; Deplacement=%d; NomEmplacement=%s; nParam=%d; Passage=%d; ptrPile=%d; \n", courant->nom, courant->typeIdentificateur, courant->typeLiteral, courant->valeur, courant->dimension, courant->emplacement, courant->deplacement, courant->nomEmplacement, courant->nParam, courant->passage, courant->ptrPile); 
			courant=courant->suivant;
		}
	}
}

void afficherLocalisation(int localisation, char *nom)
{
	switch(localisation)
	{
		case 0:
			sprintf(nom, "Global");
			break;
		case 1:
			sprintf(nom, "Fonction");
			break;
		case 2:
			sprintf(nom, "Procedure");
			break;
		default:
			sprintf(nom, "Inconnu");
			break;		
	}
}

/*Destruction de la liste*/
void nettoyerListe(struct liste *lst)
{
	if(lst!=NULL && lst->nbElem>0)
	{
		struct symbole *courant=lst->tete;

		while(courant!=NULL)
		{
			free(courant);
			lst->nbElem--;
			courant=courant->suivant;
		}

		lst->tete=lst->queue=NULL;
		lst->nbElem=0;
	}
}

void appliquerType(struct liste *lst, int TypeI, int typeL, int nParam)
{
	if(lst!=NULL)
	{
		struct symbole *tmp=lst->tete;

		while(tmp!=NULL)
		{
			tmp->typeIdentificateur=TypeI;
			tmp->typeLiteral=typeL;
			tmp->nParam=nParam;
			tmp=tmp->suivant;
		}
	}
}

void saveListe(struct liste *src, FILE *dest)
{
	if(src!=NULL && src->nbElem>0)
	{
		int i;
		char header[128];
		sprintf(header, "------------------ table des symboles ------------------\nNbSymbole=%d;\n", src->nbElem);
		fputs(header, dest);
		
		struct symbole *courant=src->tete;

		while(courant!=NULL)
		{
			char buffer[80];
			sprintf(buffer, "%s %d %d %s %d %s %d %d %d\n", courant->nom, courant->typeIdentificateur, courant->typeLiteral, courant->valeur, courant->emplacement, courant->nomEmplacement, courant->deplacement, courant->nParam, courant->passage);
			fputs(buffer, dest);
			courant=courant->suivant;
		}
	}
}

struct symbole* chercherUnSymbolePosition(struct liste* lst, int position)
{
	if(lst!=NULL)
	{
		struct symbole *courant=lst->tete;
		int i=0;

		while(courant!=NULL && i!=position)
		{
			courant=courant->suivant;
			i++;
		}

		return courant;
	}

	return NULL;
}

int chercherSymboleI(struct liste *lst, char name[128], char nomEmplacement[128])
{
	if(lst!=NULL)
	{
		struct symbole *courant=lst->tete;
		int i=0;

		while(courant!=NULL)
		{
			if(strcmp(name, courant->nom)==0 && strcmp(courant->nomEmplacement, nomEmplacement)==0) return i;
			courant=courant->suivant;
			i++;
		}

		return -1;
	}
}

/**/

// Main de test
/*main()
{
	struct liste *tmp=constrListe();
	struct liste *lst=constrListe();
	
	printf("Lst=%d\n", lst->nbElem);
	
	ajouterSimpleSymbole(lst, "x", "aucune", 0);
	ajouterSimpleSymbole(lst, "y", "aucune", 0);
	ajouterSimpleSymbole(lst, "z", "aucune", 0);
	ajouterSimpleSymbole(lst, "x", "aucune", 1);

	//affichage(lst);
	printf("-----\n");

	struct liste *trouve=chercherSymbole(lst, "x");

	if(trouve->nbElem>0)
	{
		struct symbole *courant=trouve->tete;

		while(courant!=NULL)
		{
			printf("Nom=%s; Emplacement=%d;\n", courant->nom, courant->emplacement);
			courant=courant->suivant;
		}

	}
	
	
}*/

